﻿using System;
using System.Data;
using System.Data.SQLite;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Input;
using OpenFileDialog = Microsoft.Win32.OpenFileDialog;
using SaveFileDialog = Microsoft.Win32.SaveFileDialog;

namespace Theodorus
{
	/// <summary>
	/// Interaction logic for MainWindow.xaml
	/// </summary>
	public partial class MainWindow
	{
		private readonly TheodorusModel _model = new TheodorusModel();
		private readonly IResultsRenderer _htmlRenderer = new HtmlResultsRenderer();
		private readonly IResultsRenderer _textRenderer = new TextResultsRenderer();

		public MainWindow()
		{
			InitializeComponent();
			DataContext = _model;
		}

		private void ExecuteOpen(object sender, ExecutedRoutedEventArgs e)
		{
			var cd = new ConnectionDialog
						{
							Owner = this, 
							ConnectionString = Properties.Settings.Default.DefaultConnectionString
						};

			if (cd.ShowDialog() == true)
			{
				_model.ConnectionString = cd.ConnectionString;
			}
		}

		private void ExecuteExit(object sender, ExecutedRoutedEventArgs e)
		{
			Close();
		}

		private void CanExecuteOptions(object sender, CanExecuteRoutedEventArgs e)
		{
			e.CanExecute = true;
		}

		private void ExecuteOptions(object sender, ExecutedRoutedEventArgs e)
		{
			var options = new Options {Owner = this};
			options.ShowDialog();
		}

		private void ExecuteAbout(object sender, ExecutedRoutedEventArgs e)
		{
			var box = new About {Owner = this};
			box.ShowDialog();
		}

		private void CanExecuteQuery(object sender, CanExecuteRoutedEventArgs e)
		{
			if (QueryText != null)
			{
				e.CanExecute = !String.IsNullOrEmpty(QueryText.Text);
			}
		}

		private void ExecuteQuery(object sender, ExecutedRoutedEventArgs e)
		{
			if (!String.IsNullOrEmpty(QueryText.Text))
			{
				ExecuteCommand(!String.IsNullOrEmpty(QueryText.Selection.Text) ? QueryText.Selection.Text : QueryText.Text);
			}
		}

		private void ExecuteCommand(string queryString)
		{
			_textRenderer.Reset();
			_htmlRenderer.Reset();
			var constr = _model.ConnectionString;

			using (var con = new SQLiteConnection(constr))
			{
				try
				{
					con.Open();
					
					queryString = Regex.Replace(queryString, @"--.*$", "", RegexOptions.Multiline);
					queryString = Regex.Replace(queryString, @"/\*[^*]*?\*/", "");
					var queryChunks = Regex.Split(queryString, @"^\s*GO;*\s*$",
												  RegexOptions.IgnoreCase | RegexOptions.Multiline);
					
					var cleanedQueryChunks = from item in queryChunks
											 let cleaned = item.Trim()
											 where cleaned.Length != 0
											 select cleaned;

					foreach (var query in cleanedQueryChunks)
					{
						var sw = new Stopwatch();
						sw.Start();
						using (var cmd = new SQLiteCommand(con))
						{
							try
							{
								cmd.CommandType = CommandType.Text;
								cmd.CommandText = query;

								var ds = new DataSet();
								var da = new SQLiteDataAdapter(cmd);
								da.Fill(ds);

								sw.Stop();
								
								if (ds.Tables.Count == 0)
								{
									_textRenderer.AddResponse(query, "Ok", sw.Elapsed);
									_htmlRenderer.AddResponse(query, "Ok", sw.Elapsed);
								}
								else
								{
									foreach (DataTable table in ds.Tables)
									{
										_textRenderer.AddTable(query, table, sw.Elapsed);
										_htmlRenderer.AddTable(query, table, sw.Elapsed);
									}
								}
							}
							catch (Exception ex)
							{
								_htmlRenderer.AddError(query, ex.Message);
								_textRenderer.AddError(query, ex.Message);
								
							}
						}
						
					}
				}
				finally
				{
					con.Close();
				}
			}
			
			Output.NavigateToString(_htmlRenderer.GetResults());
		}

		private void WindowsFormsHostLoaded(object sender, RoutedEventArgs e)
		{
			QueryText.ConfigurationManager.CustomLocation = "EditorStyles.xml";
			QueryText.ConfigurationManager.Language = "sqlite";
			
			QueryText.SelectionChanged += (sd, ex) => CommandManager.InvalidateRequerySuggested();			
		}

		private void ScintiallaCanCopy(object sender, CanExecuteRoutedEventArgs e)
		{
			e.CanExecute = QueryText.Selection.Length > 0;
		}

		private void ScintillaCopy(object sender, ExecutedRoutedEventArgs e)
		{
			QueryText.Clipboard.Copy();
		}

		private void ScintillaCut(object sender, ExecutedRoutedEventArgs e)
		{
			QueryText.Clipboard.Cut();
		}

		private void ScintiallaCanCut(object sender, CanExecuteRoutedEventArgs e)
		{
			e.CanExecute = QueryText.Selection.Length > 0;
		}

		private void ScintiallaCanPaste(object sender, CanExecuteRoutedEventArgs e)
		{
			e.CanExecute = QueryText.Clipboard.CanPaste;
		}

		private void ScintillaPaset(object sender, ExecutedRoutedEventArgs e)
		{
			QueryText.Clipboard.Paste();
		}

		private void ScintillaCanUndo(object sender, CanExecuteRoutedEventArgs e)
		{
			e.CanExecute = QueryText.UndoRedo.CanUndo;
		}

		private void ScintillaUndo(object sender, ExecutedRoutedEventArgs e)
		{
			QueryText.UndoRedo.Undo();
		}

		private void ScintillaCanRedo(object sender, CanExecuteRoutedEventArgs e)
		{
			e.CanExecute = QueryText.UndoRedo.CanRedo;
		}

		private void ScintillaRedo(object sender, ExecutedRoutedEventArgs e)
		{
			QueryText.UndoRedo.Redo();
		}

		private void SaveQuery(object sender, ExecutedRoutedEventArgs e)
		{
			var sfd = new SaveFileDialog
					  {
						AddExtension = true,
						DefaultExt = ".sql",
						DereferenceLinks = true,
						OverwritePrompt = true,
						RestoreDirectory = true,
						ValidateNames = true,
						Filter = "SQL Files (*.sql)|*.sql|Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
						FilterIndex = 0
					  };

			var resul = sfd.ShowDialog(this);
			if (resul == true)
			{
				File.WriteAllText(sfd.FileName, QueryText.Text);
			}
			
		}

		private void CanSaveQuery(object sender, CanExecuteRoutedEventArgs e)
		{
			e.CanExecute = QueryText.TextLength > 0;
		}

		private void CanSaveResults(object sender, CanExecuteRoutedEventArgs e)
		{
			e.CanExecute = _textRenderer.HasResults();
		}

		private void SaveResults(object sender, ExecutedRoutedEventArgs e)
		{
			var sfd = new SaveFileDialog
			{
				AddExtension = true,
				DefaultExt = ".html",
				DereferenceLinks = true,
				OverwritePrompt = true,
				RestoreDirectory = true,
				ValidateNames = true,
				Filter = "HTML Files (*.html)|*.html|Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
				FilterIndex = 0
			};

			var result = sfd.ShowDialog(this);
			if (result == true)
			{
				File.WriteAllText(sfd.FileName,
								  sfd.FileName.EndsWith("html") ? _htmlRenderer.GetResults() : _textRenderer.GetResults());
			}
		}

		private void OpenQuery(object sender, ExecutedRoutedEventArgs e)
		{
			var ofd = new OpenFileDialog
			{
				AddExtension = true,
				CheckFileExists = true,
				CheckPathExists = true,
				DefaultExt = ".sql",
				Filter = "SQL Files (*.sql)|*.sql|Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
				FilterIndex = 0,
				RestoreDirectory = true,
				Multiselect = false,
				DereferenceLinks = true,
				ValidateNames = true
			};

			var result = ofd.ShowDialog();
			if (result == true)
			{
				QueryText.Text = File.ReadAllText(ofd.FileName);
			}
		}

		private void CanOpenQuery(object sender, CanExecuteRoutedEventArgs e)
		{
			e.CanExecute = _model.IsConnected;
		}
	}
}
